home *** CD-ROM | disk | FTP | other *** search
- #line 1 "/fzi/prost/stone/SOS3-2/src/cci/cci.c"
- /* --------------------------------------------------------------------------
- * Copyright 1992 by Forschungszentrum Informatik (FZI)
- *
- * You can use and distribute this software under the terms of the licence
- * you should have received along with this program.
- * If not or if you want additional information, write to
- * Forschungszentrum Informatik, "STONE", Haid-und-Neu-Strasse 10-14,
- * D-7500 Karlsruhe 1, Germany.
- * --------------------------------------------------------------------------
- */
- // **************************************************************************
- // Module cci 03/07/90 Juergen Uhl (ju)
- // **************************************************************************
- // implements methods of classes: cci_Schema_impl, cci_Method_impl
- // **************************************************************************
-
- // --------------------------------------------------------------------------
- // Tracing conventions:
- // no tracing: string conversions for external types
- // cci_VL : symbol table patching
- // cci_L : hash table management, lookup of file names for load
- // cci_M : module initialization, local_... methods
- // cci_H : other methods
- // --------------------------------------------------------------------------
-
- #include <sys/file.h>
- #include <osfcn.h>
- #include <libc.h>
- #include <string.h>
- #include <stream.h>
- #include <sys/resource.h> // getrlimit, setrlimit
- #include <sys/param.h> // MAXPATHLEN
-
- #ifdef GNU
- #include <unistd.h> // SEEK_SET
-
- #define CAN_LOAD_INCREMENTALLY
- #endif
-
- #ifdef CAN_LOAD_INCREMENTALLY
- extern "C" {
- #include <a.out.h>
- }
-
- #if defined(MIPSEL) || defined(USG)
- #ifndef hpux
- #define exec aouthdr
- #define a_text text_start
- #define a_data data_start
- #endif
- #endif
-
- #ifdef __pyr__
- #define MUST_MPROTECT
- #include <sys/mman.h>
-
- extern "C" {
- int mprotect (char *, int, int);
- }
- #endif
- #endif CAN_LOAD_INCREMENTALLY
-
- #include "sys.h"
- #include "sos.h"
- #include "smg.h"
- #include "cci_err.h"
- #include "trc_cci.h"
- #include "cci_sos.h"
-
- typedef void (*vfct_ptr_t)();
-
- // --------------------------------------------------------------------------
-
- #ifdef CAN_LOAD_INCREMENTALLY
-
- LOCAL const char *ENVVAR_NAME = "SOSINCLOAD";
-
- LOCAL class cci_FileNames
- { public:
- char *executable, // name of running executable
- *symtab_file, // name of temporary file containing symbol table of
- // the executable as extended by previous loads
- *tmpfile, // name of temporary file used to build the next
- // version of symtab_file.
- *stdlibs, // linker options to load standard libraries
- *linker, // pathname of link editor
- *crtmodule; // pathname of object module containing the
- // startup routine for incrementally loaded code
- sos_Bool echo; // flag: echo files to be loaded
-
- cci_FileNames ();
- ~cci_FileNames ();
- } cci_file_names;
-
- cci_FileNames::cci_FileNames () {} // compiler error ??? destructor is only
- // called, if construtor is defined
- cci_FileNames::~cci_FileNames ()
- { if (symtab_file) unlink (symtab_file);
- if (tmpfile) unlink (tmpfile);
- }
- #endif CAN_LOAD_INCREMENTALLY
-
-
- // **************************************************************************
- void cci_init (char** argv)
- // **************************************************************************
- { T_PROC ("cci_init")
- TT (cci_M, T_ENTER);
-
- #ifndef CAN_LOAD_INCREMENTALLY
- TT (cci_M, T_LEAVE);
- #else
- // argv[0] is expected to contain either the absolute pathname of
- // the executable, or a relative pathname anchored at the current
- // working directory.
- if (*argv[0] EQ '/')
- cci_file_names.executable = strdup (argv[0]);
- else
- { char cwd[MAXPATHLEN];
- smg_String tmp = smg_String(getwd(cwd)) + "/" + argv[0];
-
- cci_file_names.executable = tmp.make_Cstring (SMG_TRANSFER);
- }
-
- sos_Bool do_default_init = TRUE;
- char *settings = getenv (ENVVAR_NAME);
-
- if (settings)
- { sos_Bool is_ok;
- if (is_ok = (sos_Bool) (*settings EQ '+' OR *settings EQ '-'))
- { cci_file_names.echo = (sos_Bool)(*settings EQ '+');
-
- while (*(++ settings) AND *settings EQ ' ')
- ;
- if (*settings EQ EOS)
- is_ok = FALSE;
- else
- { for (char *start = settings;
- *settings AND *settings != ' ';
- ++ settings)
- ;
- int len = settings - start;
- cci_file_names.linker = strncpy (new char[len+1], start, len);
- cci_file_names.linker[len] = EOS;
-
- while (*(++ settings) AND *settings EQ ' ')
- ;
- if (*settings EQ EOS)
- is_ok = FALSE;
- else
- { for (start = settings;
- *settings AND *settings != ' ';
- ++settings)
- ;
- len = settings - start;
- cci_file_names.crtmodule = strncpy (new char[len+1], start, len);
- cci_file_names.crtmodule[len] = EOS;
-
- cci_file_names.stdlibs = strdup (settings);
- }
- }
- }
- if (is_ok)
- do_default_init = FALSE;
- else
- err_raise (err_USE, err_CCI_WRONG_INIT, getenv (ENVVAR_NAME), FALSE);
- }
- if (do_default_init)
- { cci_file_names.stdlibs = LIBSXX;
- cci_file_names.linker = LDXX;
- cci_file_names.crtmodule = CRTXX;
- cci_file_names.echo = ECHOXX;
- }
- TT (cci_M, T_LEAVE; TXT("main"); TS(cci_file_names.executable);
- TXT("ld"); TS(cci_file_names.linker);
- TXT("crt"); TS(cci_file_names.crtmodule);
- TXT("libs"); TS(cci_file_names.stdlibs);
- TXT("echo"); TB(cci_file_names.echo));
- #endif CAN_LOAD_INCREMENTALLY
- }
-
- // --------------------------------------------------------------------------
- #if defined(CAN_LOAD_INCREMENTALLY) && defined(GNU)
- /*
- * The following is really nasty:
- * We want to use the GNU startup module crt1+.o unchanged. Unfortunately:
- * - this module must be slipped each time in front of the incrementally
- * loaded object modules, but
- * - contains an external symbol named '_initfn' which is initialized to a
- * null pointer and called (resp. the referenced function) after the global
- * constructors of the added code, and
- * - we do not use this function pointer for the initialization of the
- * loaded code.
- * Hence, the second incremental load would fail due to multiple definitions
- * of '_initfn'. Furthermore, we must initialize '_initfn' (it should point to
- * a dummy function), but we can't write this initialization in this module
- * since '_initfn' is not known before the incremental load.
- * The `solution`:
- * - Modify the temporary symbol table by making '_initfn' a filelocal symbol
- * (the original symbol table of the executable remains unchanged).
- * - This modification is done after each load.
- * - Since we know the address of '_initfn' from the symbol table, we may
- * as well use this knowledge to initialize _initfn.
- */
- LOCAL void dummy_fct()
- { T_PROC ("cci: dummy_fct")
- TT (cci_VL, T_ENTER);
- TT (cci_VL, T_LEAVE);
- }
-
- LOCAL void patch_symboltable()
- { T_PROC ("cci: patch_symboltable")
- TT (cci_VL, T_ENTER);
-
- struct exec header;
- int fd;
-
- if ((fd = open (cci_file_names.symtab_file, O_RDWR, 0)) < 0)
- err_raise (err_SYS, err_CCI_OPEN_FAILED, cci_file_names.symtab_file);
- if (read (fd, (void*)&header, sizeof(header)) != sizeof(header))
- err_raise (err_SYS, err_CCI_READ_FAILED, cci_file_names.symtab_file);
-
- off_t sym_offset = N_SYMOFF(header),
- stringbase = N_STROFF(header);
-
- // Is there a better starting point to speed up the search (end of the
- // former symboltable, maybe)?
- // Current search times seem to be well below 5% of the overall load time.
-
- char* searched = "__initfn";
- int searchedlen = strlen (searched);
- char readbuf[15];
- readbuf[searchedlen] = '\0';
-
- const int SYMBUF_SIZE = 1024 / sizeof(struct nlist);
- struct nlist symbuf[SYMBUF_SIZE];
-
- for (sos_Bool searching = TRUE; searching; )
- { if (lseek (fd, sym_offset, SEEK_SET) < 0)
- err_raise (err_SYS, err_CCI_SEEK_FAILED, cci_file_names.symtab_file);
- if (read (fd, (void*)&symbuf, sizeof(symbuf)) != sizeof(symbuf))
- err_raise (err_SYS, err_CCI_READ_FAILED, cci_file_names.symtab_file);
-
- struct nlist *sym_ptr = symbuf;
- for (int idx = SYMBUF_SIZE; --idx >= 0; ++ sym_ptr)
- { if (sym_ptr->n_type == (N_DATA | N_EXT) && sym_ptr->n_un.n_strx > 0)
- { if (lseek(fd,(off_t)(stringbase+sym_ptr->n_un.n_strx),SEEK_SET) < 0)
- err_raise (err_SYS, err_CCI_SEEK_FAILED,
- cci_file_names.symtab_file);
- if (read (fd, (void*)&readbuf, searchedlen) <= 0)
- err_raise (err_SYS, err_CCI_READ_FAILED,
- cci_file_names.symtab_file);
- if (streql (readbuf, searched))
- { * (vfct_ptr_t*)sym_ptr->n_value = dummy_fct; // set _initfn
- sym_ptr->n_type &= ~N_EXT; // clear external bit
-
- if (lseek (fd, sym_offset, SEEK_SET) < 0)
- err_raise (err_SYS, err_CCI_SEEK_FAILED,
- cci_file_names.symtab_file);
- if (write (fd, (void*)sym_ptr, sizeof(struct nlist))
- < sizeof(struct nlist))
- err_raise (err_SYS, err_CCI_WRITE_FAILED,
- cci_file_names.symtab_file);
-
- searching = FALSE;
- break;
- }
- }
- if ((sym_offset += sizeof(struct nlist)) >= stringbase)
- err_raise (err_SYS, "symbol __initfn not found", NULL, FALSE);
- } // for (... idx ...)
- } // for (... searching ...)
- close (fd);
-
- TT (cci_VL, T_LEAVE);
- }
- #endif CAN_LOAD_INCREMENTALLY && GNU
-
-
- // --------------------------------------------------------------------------
- // conversions for external type cci_Fun
- // --------------------------------------------------------------------------
-
- sos_String make_string_from_cci_Fun_object (sos_Object f)
- { cci_Fun p1 = make_cci_Fun (f);
- sos_String result
- = smg_String ((sos_Int)p1, FALSE).make_String (TEMP_CONTAINER);
- return result;
- }
-
- sos_Object make_cci_Fun_object_from_string (sos_String s)
- { sos_Cstring s1 = s.make_Cstring();
- sos_Cstring ptr;
- long l = strtol (s1, &ptr, 16);
- delete s1;
-
- sos_Object result = (ptr != s1 AND ptr[0] == 0)
- ? make_cci_Fun_object (cci_Fun (l))
- : NO_OBJECT;
- return result;
- }
-
-
- // --------------------------------------------------------------------------
- // LOCAL: Management of loaded schema implementations
- // (A schema is identified by its associated schema container.)
- // --------------------------------------------------------------------------
- #define CNT_HTAB_SIZE 128
-
- struct cci_CntEntry {
- cci_CntEntry *next;
- sos_Container ct;
- };
- LOCAL cci_CntEntry *cnt_htab[CNT_HTAB_SIZE];
-
- #ifdef CAN_LOAD_INCREMENTALLY
- // The following array is used in 'lookup_files' to prevent from processing
- // a schema (container) twice, and afterwards in 'cci_Schema_impl::load' to
- // enter the newly loaded schemas (resp. their containers) into the hash table.
- LOCAL struct {
- sos_Container *array;
- int size,
- last_entry; } cnt_array = { NULL, 0, -1 };
-
- // *************************************************************************
- LOCAL sos_Bool enter_ct (sos_Container ct)
- // *************************************************************************
- { T_PROC ("enter_ct")
- TT (cci_L, T_ENTER);
-
- for (int i = 0; i <= cnt_array.last_entry; ++ i)
- if (ct EQ cnt_array.array[i])
- { TT (cci_L, T_LEAVE; TB(FALSE));
- return FALSE;
- }
-
- if (++cnt_array.last_entry EQ cnt_array.size)
- { sos_Container *tmp;
- if (cnt_array.size)
- { tmp = new sos_Container[cnt_array.size *= 2];
- bcopy ((char*)cnt_array.array,
- (char*)tmp,
- cnt_array.last_entry * (int)sizeof(sos_Container));
- delete cnt_array.array;
- }
- else
- tmp = new sos_Container[cnt_array.size = 4];
- cnt_array.array = tmp;
- }
- cnt_array.array[cnt_array.last_entry] = ct;
-
- TT (cci_L, T_LEAVE; TB(TRUE));
- return TRUE;
- }
- #endif CAN_LOAD_INCREMENTALLY
-
- // *************************************************************************
- LOCAL sos_Bool enter_schema (sos_Container ct, sos_Bool enter_if_new = TRUE)
- // *************************************************************************
- { T_PROC ("enter_schema")
- TT (cci_L, T_ENTER);
-
- sos_Bool new_schema;
-
- for (cci_CntEntry **e = &cnt_htab[ct % CNT_HTAB_SIZE];
- *e AND (*e)->ct != ct;
- e = &(*e)->next)
- {}
- if (*e)
- new_schema = FALSE;
- else
- { new_schema = TRUE;
-
- if (enter_if_new)
- { *e = new cci_CntEntry;
- (*e)->next = NULL;
- (*e)->ct = ct;
- }
- }
-
- TT (cci_L, T_LEAVE; TI((int)ct); TB(new_schema));
- return new_schema;
- }
-
- // *************************************************************************
- LOCAL void load_schema (sos_Container ct)
- // *************************************************************************
- { T_PROC ("load_schema")
- TT (cci_L, T_ENTER);
-
- // This routine is the entry point to the incremental loading facility
- // for the generated code, in particular via the C::make() calls.
-
- for (cci_CntEntry **e = &cnt_htab[ct % CNT_HTAB_SIZE];
- *e AND (*e)->ct != ct;
- e = &(*e)->next)
- {}
- if (*e == NULL) // schema not yet loaded
- { sos_Bool found = FALSE;
- sos_Schema_module sm = sos_Schema_module::retrieve (ct);
- sos_Schema_impl_List sil = sm.get_impls();
- if (sil != NO_OBJECT)
- agg_iterate (sil, sos_Schema_impl si)
- if (si.isa (cci_Schema_impl_type))
- { cci_Schema_impl::make (si).load();
- found = TRUE;
- break;
- }
- agg_iterate_end (sil, si);
-
- if (NOT found)
- err_raise (err_SYS, err_CCI_INC_LOAD_FAILED,
- sm.get_name().make_Cstring());
- }
- TT (cci_L, T_LEAVE);
- }
-
- // *************************************************************************
- LOCAL inline void schema_is_loaded (sos_Container ct)
- // *************************************************************************
- { enter_schema (ct, TRUE);
- }
-
- #ifdef CAN_LOAD_INCREMENTALLY
- // *************************************************************************
- LOCAL void lookup_files (sos_Container ct,
- sos_String_List objects,
- sos_String_List libraries)
- // *************************************************************************
- { T_PROC ("cci : lookup_files")
- TT (cci_L, T_ENTER; TXT("container"); TI((int)ct));
-
- sos_Schema_module sm = sos_Schema_module::retrieve (ct);
-
- // first step: (recursively) add file names for imported schemas
- // not yet loaded
- sos_Imports impl = sm.get_imports();
- if (impl != NO_OBJECT)
- agg_iterate (impl, sos_Schema_module imp)
- sos_Container imp_ct = imp.container();
- if (enter_schema (imp_ct, FALSE) AND enter_ct (imp_ct))
- lookup_files (imp_ct, objects, libraries);
- agg_iterate_end (impl, imp);
-
- cci_Schema_impl si = cci_Schema_impl::make (NO_OBJECT);
- sos_Schema_impl_List sil = sm.get_impls();
- if (sil != NO_OBJECT)
- agg_iterate (sil, sos_Schema_impl i)
- if (i.isa (cci_Schema_impl_type))
- { si = cci_Schema_impl::make (i);
- break;
- }
- agg_iterate_end (sil, i);
-
- if (si EQ NO_OBJECT)
- err_raise (err_SYS, err_CCI_INC_LOAD_FAILED,
- sm.get_name().make_Cstring());
-
- // second step: (recursively) add file names for schemas this schema
- // depends on and which are not yet loaded
- sos_String_List sl = si.get_schemas();
- if (sl != NO_OBJECT)
- agg_iterate (sl, sos_String s)
- sos_Schema_module sm = sos_Schema_module::lookup (s);
- if (sm EQ NO_OBJECT)
- err_raise (err_SYS, err_CCI_UNKNOWN_SCHEMA,
- sm.get_name().make_Cstring());
-
- sos_Container imp_ct = sm.container();
- if (enter_schema (imp_ct, FALSE) AND enter_ct (imp_ct))
- lookup_files (imp_ct, objects, libraries);
- agg_iterate_end (sl, s);
-
- // third step: process the direct dependencies of this schema on
- // object modules, libraries
- if ((sl = si.get_object_files()) != NO_OBJECT)
- objects += sl;
-
- if ((sl = si.get_libraries()) != NO_OBJECT)
- libraries += sl;
-
- TT (cci_L, T_LEAVE);
- }
- #endif CAN_LOAD_INCREMENTALLY
-
-
- // --------------------------------------------------------------------------
- // class cci_Schema_impl
- // --------------------------------------------------------------------------
- // *************************************************************************
- cci_Schema_impl _cci_Schema_impl::make_impl (sos_Schema_module s)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::make_impl")
- TT (cci_H, T_ENTER);
-
- cci_Schema_impl result;
- sos_Bool found = FALSE;
-
- sos_Schema_impl_List impls = s.get_impls();
- if (impls == NO_OBJECT)
- { impls = sos_Schema_impl_List::create (s.container());
- s.set_impls (impls);
- }
- else
- agg_iterate (impls, sos_Schema_impl impl)
- if (impl.isa (cci_Schema_impl_type))
- { found = TRUE;
- result = cci_Schema_impl::make (impl);
- break;
- }
- agg_iterate_end (impls, impl);
-
- if (NOT found)
- { result = cci_Schema_impl::create (s.container());
- impls.append (result);
- }
-
- TT (cci_H, T_LEAVE);
- return result;
- }
-
-
- // **************************************************************************
- void _cci_Schema_impl::load (sos_Typed_id &_tpid)
- // **************************************************************************
- { T_PROC ("cci_Schema_impl::load")
- TT (cci_H, T_ENTER);
-
- if (NOT enter_schema (cci_Schema_impl::make(_tpid,this).container(), FALSE))
- { TT (cci_H, T_LEAVE);
- return;
- }
-
- #ifndef CAN_LOAD_INCREMENTALLY
- err_raise (err_SYS, err_CCI_INC_LOAD_NOT_IMPL, NULL, FALSE);
- sos_Offset o = cci_Schema_impl::make(_tpid,this).offset(); // only to avoid AT&T compiler warnings!
- #else
- int fd;
- struct exec header;
-
- if (cci_file_names.executable EQ NULL)
- err_raise (err_SYS, err_CCI_NOT_INITIALIZED, NULL, FALSE);
-
- cnt_array.last_entry = -1;
- enter_ct (cci_Schema_impl::make(_tpid,this).container());
-
- sos_String_List objects = sos_String_List::create (TEMP_CONTAINER, FALSE);
- sos_String_List libs = sos_String_List::create (TEMP_CONTAINER, FALSE);
-
- int hidden_objects = 1;
- objects.append (smg_String(cci_file_names.crtmodule)
- .make_String (TEMP_CONTAINER));
-
- lookup_files (cci_Schema_impl::make(_tpid,this).container(), objects, libs);
-
- if (objects.card() EQ hidden_objects)
- err_raise (err_SYS, err_CCI_INC_LOAD_FAILED, NULL, FALSE);
-
- if (cci_file_names.symtab_file EQ NULL)
- { smg_String tmpfile = smg_String("") + sos_tempdir + "/sosdm.XXXXXX";
- cci_file_names.symtab_file = tmpfile.make_Cstring (SMG_TRANSFER);
- mktemp (cci_file_names.symtab_file);
-
- tmpfile = smg_String("") + sos_tempdir + "/sosdf.XXXXXX";
- cci_file_names.tmpfile = tmpfile.make_Cstring (SMG_TRANSFER);
- mktemp (cci_file_names.tmpfile);
-
- TT (cci_M, TXT("tmp.symtab"); TS(cci_file_names.symtab_file);
- TXT("tmp.file"); TS(cci_file_names.tmpfile));
-
- smg_String cmd = smg_String("ln -s ") + cci_file_names.executable + " "
- + cci_file_names.symtab_file;
- if (system (cmd.make_Cstring (SMG_BORROW)))
- err_raise (err_SYS, err_CCI_LINK_FAILED, NULL, FALSE);
- }
-
- unsigned size = 0;
- smg_String cmd_head = smg_String("umask 111;")
- + cci_file_names.linker
- + " -N -A " + cci_file_names.symtab_file
- + " -T ";
- smg_String cmd_tail = smg_String(" -o ") + cci_file_names.tmpfile;
-
- agg_iterate (objects, sos_String on)
- { smg_String obj_module = on;
- sos_Cstring obj_name = obj_module.make_Cstring (SMG_BORROW);
-
- if ((fd = open (obj_name, O_RDONLY, 0)) < 0)
- err_raise (err_SYS, err_CCI_OPEN_FAILED, obj_name);
- if (read (fd, (void*) &header, sizeof (header)) != sizeof (header))
- err_raise (err_SYS, err_CCI_READ_HEADER_FAILED, obj_name);
-
- size += header.a_text + header.a_data + header.a_bss;
- cmd_tail += smg_String(" ") + obj_module;
-
- close (fd);
-
- if (cci_file_names.echo AND --hidden_objects < 0)
- cerr << "...loading " << obj_name << "\n";
- }
- agg_iterate_end (objects, on);
-
- agg_iterate (libs, sos_String ln)
- cmd_tail += smg_String(" ") + ln;
- agg_iterate_end (libs, ln);
-
- cmd_tail += smg_String(" ") + cci_file_names.stdlibs;
-
- #ifdef EXEC_PAGESIZE
- int pagsiz = EXEC_PAGESIZE;
- #elif defined(PAGSIZ)
- int pagsiz = PAGSIZ;
- #else
- int pagsiz = getpagesize();
- #endif
-
- if (size > 81920) // Add 8K in case of bigger files to increase the
- size += 8192; // chance that the first size guess will suffice.
-
- unsigned actual_size;// Repeat until size >= actual size.
- char *obj_addr; // (The first guess might be to small because the
- for (;;) // size of the BSS-Segment and the size of code
- // loaded from libraries is not yet known.)
- { size += pagsiz - 1;
- char *allocated = new char[size];
-
- obj_addr = (char*)( ((unsigned)allocated + pagsiz - 1) & ~(pagsiz-1) );
- size -= obj_addr - allocated;
- // place additional object modules on page boundary
-
- smg_String ldcmd = cmd_head + smg_String((sos_Int)obj_addr, FALSE)
- + cmd_tail;
-
- TT (cci_M, TXT("load command"); TS(ldcmd.make_Cstring (SMG_BORROW)));
-
- struct rlimit core_limit;
- getrlimit (RLIMIT_CORE, &core_limit);
- int cur_limit = core_limit.rlim_cur;
- core_limit.rlim_cur = 0;
- setrlimit (RLIMIT_CORE, &core_limit);
- // suppress core file creation temporarily
-
- int error_status = system (ldcmd.make_Cstring (SMG_BORROW));
-
- core_limit.rlim_cur = cur_limit;
- setrlimit (RLIMIT_CORE, &core_limit);
-
- if (error_status)
- { unlink (cci_file_names.tmpfile);
- err_raise (err_SYS, err_CCI_LOAD_FAILED, NULL, FALSE);
- }
-
- fd = open (cci_file_names.tmpfile, O_RDONLY, 0);
- read (fd, (void*) &header, sizeof (header));
- close (fd);
-
- actual_size = header.a_text + header.a_data + header.a_bss;
- if (actual_size <= size) break;
-
- TT (cci_M, TXT("...repeat loading");
- TXT("size guess"); TI(size);
- TXT("actual size"); TI(actual_size));
-
- delete allocated;
- size = actual_size;
- }
-
- smg_String cmd = smg_String("rm ") + cci_file_names.symtab_file
- + ";mv " + cci_file_names.tmpfile
- + " " + cci_file_names.symtab_file;
- if (system (cmd.make_Cstring (SMG_BORROW)))
- err_raise (err_SYS, err_CCI_MOVE_FAILED, NULL, FALSE);
-
- fd = open (cci_file_names.symtab_file, O_RDONLY, 0);
- if (lseek (fd, (off_t)N_TXTOFF(header), SEEK_SET) < 0)
- err_raise (err_SYS, err_CCI_SEEK_FAILED, NULL, FALSE);
-
- if (read (fd, obj_addr, actual_size) != actual_size)
- err_raise (err_SYS, err_CCI_READ_FAILED, NULL, FALSE);
- close (fd);
-
- #ifdef MUST_MPROTECT
- if (mprotect (obj_addr, actual_size, PROT_READ|PROT_EXEC|PROT_WRITE))
- err_raise (err_SYS, err_CCI_MKEXEC_FAILED, NULL, FALSE);
- #endif MUST_MPROTECT
-
- patch_symboltable();
-
- (* (vfct_ptr_t)obj_addr)(); // call startup routine of crtmodule.
-
- for (int i = 0; i <= cnt_array.last_entry; ++ i)
- schema_is_loaded (cnt_array.array[i]);
-
- #endif CAN_LOAD_INCREMENTALLY
- TT (cci_H, T_LEAVE);
- }
-
- // *************************************************************************
- void _cci_Schema_impl::local_assign (cci_Schema_impl dest, sos_Object src_o)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::local_assign")
- TT (cci_M, T_ENTER);
-
- cci_Schema_impl src = cci_Schema_impl::make (src_o);
-
- dest.get_object_files().assign (src.get_object_files());
- dest.get_libraries().assign (src.get_libraries());
- dest.get_schemas().assign (src.get_schemas());
-
- TT (cci_M, T_LEAVE);
- }
-
- // *************************************************************************
- void _cci_Schema_impl::local_initialize (cci_Schema_impl impl)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::local_initialize")
- TT (cci_M, T_ENTER);
-
- sos_Container ct = impl.container();
-
- impl.set_object_files (sos_String_List::create (ct, TRUE));
- impl.set_libraries (sos_String_List::create (ct, TRUE));
- impl.set_schemas (sos_String_List::create (ct, TRUE));
-
- TT (cci_M, T_LEAVE);
- }
-
- // *************************************************************************
- void _cci_Schema_impl::local_finalize (cci_Schema_impl impl)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::local_finalize")
- TT (cci_M, T_ENTER);
-
- impl.get_object_files().destroy();
- impl.get_libraries().destroy();
- impl.get_schemas().destroy();
-
- TT (cci_M, T_LEAVE);
- }
-
-
- // --------------------------------------------------------------------------
- // class cci_Schema_impl : Management of dynamic type representation objects
- // --------------------------------------------------------------------------
- #define MAKE_OBJ_HTAB_SIZE 1024
-
- struct cci_MakeObjEntry {
- cci_MakeObjEntry *next;
- sos_Id f, t;
- cci_Make_obj obj;
- };
-
- LOCAL cci_MakeObjEntry *make_obj_htab[MAKE_OBJ_HTAB_SIZE];
-
- // *************************************************************************
- cci_Make_obj _cci_Schema_impl::get_make_obj (sos_Id t, sos_Id f)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::get_make_obj")
- TT (cci_L, T_ENTER);
-
- if (f.offset() == 0 AND (sos_Int)f.container() == 0) // type of NO_OBJECT
- f = t;
-
- int hash = (f.offset() ^ (sos_Int) f.container()
- ^ ((t.offset() ^ (sos_Int) t.container()) >> 4))
- % MAKE_OBJ_HTAB_SIZE;
-
- cci_Make_obj result;
-
- for (sos_Bool first_lookup = TRUE; ; first_lookup = FALSE)
- { for (cci_MakeObjEntry **e = &make_obj_htab[hash];
- *e AND ((*e)->f != f OR (*e)->t != t);
- e = &(*e)->next)
- {}
-
- if (*e)
- { result = (*e)->obj;
- break;
- }
- else if (first_lookup)
- #if BOOT
- err_raise (err_SYS, err_CCI_INVALID_MAKE,
- "cci_Schema_impl::get_make_obj", FALSE);
- #else
- load_schema (f.container());
- #endif
- else
- {
- sos_Type tp = sos_Type::make (sos_Typed_id::make (f));
- sos_Type rt = tp.root();
- #ifdef ATT
- if (tp.operator!=(rt))
- #else
- if (tp != rt)
- #endif
- result = cci_Schema_impl::get_make_obj (t, rt.typed_id().get_id());
- else
- err_raise (err_SYS, err_CCI_INVALID_MAKE,
- "cci_Schema_impl::get_make_obj", FALSE);
- break;
- }
- }
- TT (cci_L, T_LEAVE);
- return result;
- }
-
- // *************************************************************************
- void _cci_Schema_impl::enter_make_obj (sos_Id t, sos_Id f, cci_Make_obj obj)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::enter_make_obj")
- TT (cci_L, T_ENTER);
-
- schema_is_loaded (f.container());
-
- int hash = (f.offset() ^ (sos_Int) f.container()
- ^ ((t.offset() ^ (sos_Int) t.container()) >> 4))
- % MAKE_OBJ_HTAB_SIZE;
-
- for (cci_MakeObjEntry **e = &make_obj_htab[hash];
- *e AND ((*e)->f != f OR (*e)->t != t);
- e = &((*e)->next))
- {}
-
- if (! *e)
- { *e = new cci_MakeObjEntry;
- (*e)->next = NULL;
- (*e)->f = f;
- (*e)->t = t;
- (*e)->obj = obj;
- }
- TT (cci_L, T_LEAVE);
- }
-
-
- // --------------------------------------------------------------------------
- // class cci_Schema_impl : C++ method implementation management
- // --------------------------------------------------------------------------
- #define FUN_HTAB_SIZE 1024
-
- struct cci_Fun_entry {
- cci_Fun_entry* next;
- sos_Id m;
- cci_Fun fun;
- };
- LOCAL cci_Fun_entry *fun_htab[FUN_HTAB_SIZE];
-
- // *************************************************************************
- cci_Fun _cci_Schema_impl::get_fun (sos_Id m)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::get_fun")
- TT (cci_L, T_ENTER);
-
- load_schema (m.container());
-
- int hash = (m.offset() ^ (sos_Int) m.container()) % FUN_HTAB_SIZE;
-
- for (cci_Fun_entry **e = &fun_htab[hash];
- *e AND (*e)->m != m;
- e = &(*e)->next)
- {}
-
- cci_Fun fun;
- if (*e)
- fun = (*e)->fun;
- else
- err_raise (err_SYS, err_CCI_INVALID_METHOD,
- "cci_Schema_impl::get_fun", FALSE);
-
- TT (cci_L, T_LEAVE);
- return fun;
- }
-
- // *************************************************************************
- void _cci_Schema_impl::enter_fun (sos_Id m, cci_Fun fun)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::enter_fun")
- TT (cci_L, T_ENTER);
-
- int hash = (m.offset() ^ (sos_Int) m.container()) % FUN_HTAB_SIZE;
-
- for (cci_Fun_entry **e = &fun_htab[hash];
- *e AND NOT ((*e)->m == m);
- e = &((*e)->next))
- {}
- if (! *e)
- { *e = new cci_Fun_entry;
- (*e)->next = NULL;
- (*e)->m = m;
- (*e)->fun = fun;
- }
- TT (cci_L, T_LEAVE);
- }
-
- // *************************************************************************
- void _cci_Schema_impl::enter_string_io (sos_Id et,
- cci_IO_fun from_extern,
- cci_IO_fun to_extern)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::enter_string_io")
- TT (cci_L, T_ENTER);
-
- sos_Id et1 = sos_Id::make (et.container(), et.offset() + 1);
-
- cci_Schema_impl::enter_fun (et , (cci_Fun)from_extern);
- cci_Schema_impl::enter_fun (et1, (cci_Fun)to_extern);
-
- TT (cci_L, T_LEAVE);
- }
-
-
- // --------------------------------------------------------------------------
- // class cci_Schema_impl : generic conversions for external types
- // --------------------------------------------------------------------------
-
- typedef sos_Object (*cci_cnv_from_string)(sos_String);
- typedef sos_String (*cci_cnv_to_string)(sos_Object);
-
- // *************************************************************************
- sos_Object _cci_Schema_impl::extern_object_from_string (sos_Type tp,
- sos_String s)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::extern_object_from_string")
- TT (cci_H, T_ENTER);
-
- sos_Id id = tp.typed_id().get_id();
- sos_Id id1 = sos_Id::make (id.container(), id.offset() + 1);
-
- sos_Object result
- = (* (cci_cnv_from_string)(cci_Schema_impl::get_fun (id1)) ) (s);
-
- TT (cci_H, T_LEAVE);
- return result;
- }
-
- // *************************************************************************
- sos_String _cci_Schema_impl::string_from_extern_object (sos_Object o)
- // *************************************************************************
- { T_PROC ("cci_Schema_impl::string_from_extern_object")
- TT (cci_H, T_ENTER);
-
- sos_Id id = o.typed_id().get_tp();
-
- sos_String result
- = (* (cci_cnv_to_string)(cci_Schema_impl::get_fun (id)) ) (o);
-
- TT (cci_H, T_LEAVE);
- return result;
- }
-
-
- // --------------------------------------------------------------------------
- // class cci_Method_impl
- // --------------------------------------------------------------------------
- // *************************************************************************
- cci_Method_impl _cci_Method_impl::make_impl (sos_Method m)
- // *************************************************************************
- { T_PROC ("cci_Method_impl::make_impl")
- TT (cci_H, T_ENTER);
-
- cci_Method_impl result;
- sos_Bool found = FALSE;
-
- sos_Method_impl_List impls = m.get_impls();
- if (impls == NO_OBJECT)
- { impls = sos_Method_impl_List::create (m.container());
- m.set_impls (impls);
- }
- else
- { agg_iterate (impls, sos_Method_impl impl)
- if (impl.isa (cci_Method_impl_type))
- { found = TRUE;
- result = cci_Method_impl::make (impl);
- break;
- }
- agg_iterate_end (impls, impl);
- }
-
- if (NOT found)
- { result = cci_Method_impl::create (m.container());
- impls.append (result);
- }
- TT (cci_H, T_LEAVE);
- return result;
- }
-
- // *************************************************************************
- void _cci_Method_impl::enter_fun (sos_Typed_id &_tpid,cci_Fun fun)
- // *************************************************************************
- { T_PROC ("cci_Method_impl::enter_fun")
- TT (cci_L, T_ENTER);
-
- cci_Schema_impl::enter_fun (cci_Method_impl::make(_tpid,this).typed_id().get_id(), fun);
-
- TT (cci_L, T_LEAVE);
- }
-
- // *************************************************************************
- sos_Object _cci_Method_impl::execute (sos_Typed_id &_tpid,sos_Object o, sos_Object_Array p)
- // *************************************************************************
- { T_PROC ("cci_Method_impl::execute")
- TT (cci_H, T_ENTER);
-
- sos_Object result;
- cci_Fun f = cci_Schema_impl::get_fun (cci_Method_impl::make(_tpid,this).typed_id().get_id());
-
- result = (*f) (o, p);
-
- TT (cci_H, T_LEAVE);
- return result;
- }
-
- // *************************************************************************
- sos_String _cci_Method_impl::operator_string (sos_String op_name)
- // *************************************************************************
- { T_PROC ("cci_Method_impl::operator_string")
- TT (cci_H, T_ENTER);
-
- smg_String op_string = op_name;
- smg_String result_string;
- sos_String result;
-
- if (op_string.equal ("+") ) result_string = "__plus";
- else if (op_string.equal ("-") ) result_string = "__minus";
- else if (op_string.equal ("*") ) result_string = "__times";
- else if (op_string.equal ("/") ) result_string = "__div";
- else if (op_string.equal ("%") ) result_string = "__rem";
- else if (op_string.equal ("^") ) result_string = "__xor";
- else if (op_string.equal ("&") ) result_string = "__and";
- else if (op_string.equal ("|") ) result_string = "__or";
- else if (op_string.equal ("~") ) result_string = "__not";
- else if (op_string.equal ("!") ) result_string = "__logical_not";
- else if (op_string.equal ("=") ) result_string = "__assign";
- else if (op_string.equal ("<") ) result_string = "__less";
- else if (op_string.equal (">") ) result_string = "__greater";
- else if (op_string.equal ("+=") ) result_string = "__plus_assign";
- else if (op_string.equal ("-=") ) result_string = "__minus_assign";
- else if (op_string.equal ("*=") ) result_string = "__times_assign";
- else if (op_string.equal ("/=") ) result_string = "__div_assign";
- else if (op_string.equal ("%=") ) result_string = "__rem_assign";
- else if (op_string.equal ("^=") ) result_string = "__xor_assign";
- else if (op_string.equal ("&=") ) result_string = "__and_assign";
- else if (op_string.equal ("|=") ) result_string = "__or_assign";
- else if (op_string.equal ("<<") ) result_string = "__shift_left";
- else if (op_string.equal (">>") ) result_string = "__shift_right";
- else if (op_string.equal (">>=")) result_string = "__shift_right_assign";
- else if (op_string.equal ("<<=")) result_string = "__shift_left_assign";
- else if (op_string.equal ("==") ) result_string = "__equal";
- else if (op_string.equal ("!=") ) result_string = "__not_equal";
- else if (op_string.equal ("<=") ) result_string = "__less_equal";
- else if (op_string.equal (">=") ) result_string = "__greater_equal";
- else if (op_string.equal ("&&") ) result_string = "__logical_and";
- else if (op_string.equal ("||") ) result_string = "__logical_or";
- else if (op_string.equal ("++") ) result_string = "__increment";
- else if (op_string.equal ("--") ) result_string = "__decrement";
- else if (op_string.equal (",") ) result_string = "__comma";
- else if (op_string.equal ("->*")) result_string = "__member_access";
- else if (op_string.equal ("->") ) result_string = "__access";
- else if (op_string.equal ("()") ) result_string = "__function";
- else if (op_string.equal ("[]") ) result_string = "__index";
- else result_string = op_string;
-
- result = result_string.make_String (TEMP_CONTAINER);
-
- TT (cci_H, T_LEAVE);
- return result;
- }
-